/**********************************************************
    COPYRIGHT
        KND, Inc. (c) 2011
    CLASS NAME
        platform_adc.c
    DEPENDENCY

    HISTORY
		09/17/2011, created by Guangxing Liu
**********************************************************/
#include "platform_adc.h"
#include "platform_config.h"
#include "platform_uart.h"
#include "lpc177x_8x_adc.h"

/************************************************************************
	FUNCTION NAME : platform_adc_init
	INPUTS: 
		none
	OUTPUTS:	
		none
	DESCRIPTION:	
		Platform adc value init
************************************************************************/
void platform_adc_init(void)
{
	
}

/************************************************************************
	FUNCTION NAME : platform_adc_device_open
	INPUTS: 
		none
	OUTPUTS:	
		none
	DESCRIPTION:	
		adc Device Open
************************************************************************/
DeviceHandle platform_adc_device_open(void)
{
	platform_adc_app_call* handle = (platform_adc_app_call*)malloc(sizeof(platform_adc_app_call));
	if(handle)
	{
		handle->iOpt = Platform_Adc_App_Call_None;
	}
	return (DeviceHandle)handle;
 }	

/************************************************************************
	FUNCTION NAME : platform_adc_device_close
	INPUTS: 
		DeviceHandle handle
	OUTPUTS:	
		none
	DESCRIPTION:	
		adc Device Close
************************************************************************/
int platform_adc_device_close(DeviceHandle handle)
{
	platform_adc_app_call* me = (platform_adc_app_call*)handle;
	if(me)
	{
		free(me);
	}
	return 0;
	
}/************************************************************************
	FUNCTION NAME : platform_adc_device_ioctl
	INPUTS: 
		DeviceHandle handle, const char *params
	OUTPUTS:	
		none
	DESCRIPTION:	
		adc Device Control
************************************************************************/
int platform_adc_device_ioctl(DeviceHandle handle, const char *params)
{
	platform_adc_app_call* me = (platform_adc_app_call*)handle;
	
	switch(*params)
	{
		case '0':
			me->iOpt = Platform_Adc_App_Call_Adc_Init;
			return 0;
		case '1':
			me->iOpt = Platform_Adc_App_Call_Adc_Getadcvalue;
			return 0;
		case '2':
			me->iOpt = Platform_Adc_App_Call_Adc_Config;
			return 0;

		default:
			platform_printf("ERROR--platform_adc_device_ioctl unkown params: %s\r\n",params);
			break;
	}

	return -1;
}

/************************************************************************
	FUNCTION NAME :platform_adc_device_read
	INPUTS: 
		DeviceHandle handle, char *buf, int len
	OUTPUTS:	
		none
	DESCRIPTION:	
		adc Device Read
************************************************************************/
int platform_adc_device_read(DeviceHandle handle, void *buf, int len)
{
	platform_adc_app_call* me = (platform_adc_app_call*)handle;
	static unsigned char first_used=1;
	
	if(!me || !buf)
		return -1;
	switch(me->iOpt)
	{
		case Platform_Adc_App_Call_Adc_Getadcvalue:
			{
				platform_adc_value* adc_value = (platform_adc_value*)buf;
						
				while(ADC_ChannelGetStatus(LPC_ADC, adc_value->channel, ADC_DATA_DONE) != SET);
				

				adc_value->value= ADC_ChannelGetData(LPC_ADC, adc_value->channel);
				
				LPC_ADC ->CR &= 0xF8FFFFFF;	/* stop ADC now */

				ADC_ChannelCmd(LPC_ADC, adc_value->channel, DISABLE);
				
			}
			
	         	return 0;//conversion complete
		default:
			platform_printf("ERROR--platform_adc_device_read unkown params: %s\r\n",me->iOpt);
			break;
	}
	
	return -1;

}

/************************************************************************
	FUNCTION NAME : platform_adc_device_write
	INPUTS: 
		DeviceHandle handle,  const char *buf, int len
	OUTPUTS:	
		none
	DESCRIPTION:	
		adc Device Write
************************************************************************/
int platform_adc_device_write(DeviceHandle handle,  void *buf, int len)
{
	platform_adc_app_call* me = (platform_adc_app_call*)handle;
	if(!me || !buf)
		return -1;
	switch(me->iOpt)
	{
		case Platform_Adc_App_Call_Adc_Init:
			{
				platform_adc_config *adc_config = (platform_adc_config *)buf;

				ADC_Init(LPC_ADC,adc_config->rate);

				#ifdef LPC1754
			
				//p0.25
				PINCON->PINSEL1 |= 0x40000;//ADC0.2
				//p0.26
				PINCON->PINSEL1 |= 0x100000;//ADC0.3
				//p1.30
				PINCON->PINSEL3 |= 0x30000000;//ADC0.4
				//p1.31
				PINCON->PINSEL3 |= 0xc0000000;//ADC0.5
				//p0.3
				PINCON->PINSEL0 |= 0x00000080;//ADC0.6
				//p0.2
				PINCON->PINSEL0 |= 0x00000020;//ADC0.7

				#else

				PINSEL_ConfigPin(0,25,1);//p0.25

				PINSEL_ConfigPin(0,26,1);//p0.26

				PINSEL_ConfigPin(1,30,3);//p1.30

				PINSEL_ConfigPin(1,31,3);//p1.31

				PINSEL_ConfigPin(0,12,3);//p0.12

				PINSEL_ConfigPin(0,13,3);//p0.2

				#endif

				
			}
			return 0;
		case Platform_Adc_App_Call_Adc_Config:
			{
				platform_adc_config *adc_config = (platform_adc_config *)buf;
				
				ADC_IntConfig(LPC_ADC, adc_config->channel_intr, DISABLE);

				LPC_ADC ->CR &= 0xFFFFFF00; 
				
				ADC_ChannelCmd(LPC_ADC, adc_config->channel, ENABLE);

				ADC_StartCmd(LPC_ADC, ADC_START_NOW);

			}
			return 0;
		default:
			platform_printf("ERROR--platform_adc_device_write unkown params: %s\r\n",me->iOpt);
			break;
	}
	return -1;

}
/************************************************************************
	FUNCTION NAME : platform_init_adc_device
	INPUTS: 
		none
	OUTPUTS:	
		none
	DESCRIPTION:	
		adc Device Init
************************************************************************/
void platform_init_adc_device(void)
{
	DeviceInterface adc = {
                               platform_adc_device_open,
                               platform_adc_device_close,
                               platform_adc_device_ioctl,
                               platform_adc_device_read,
                               platform_adc_device_write
                              };


	hyacinth_install_device(ADC_DEVICE,&adc);
}

/************************************************************************
	FUNCTION NAME : platform_finit_adc_device
	INPUTS: 
		none
	OUTPUTS:	
		none
	DESCRIPTION:	
		adc Device Finit
************************************************************************/
void platform_finit_adc_device(void)
{
	hyacinth_uninstall_device(ADC_DEVICE);
}
























